#include "MyMqtt.h"
#include <Arduino.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "driver/temp_sensor.h"
// 自定义模块
#include "Config.h"
#include "WifiModule/MyWifi.h"
#include "OledModule/Oled.h"
#include "Ota/Ota.h"
#include "Senser/Switch.h"
#include "Senser/SenserConfig.h"

boolean showMqStatus = false; // 是否正在显示mq的消息,防止刷新wifi信息覆盖屏幕

// 定义主板上的 LED
const int ledPin = 8;
bool isBlinking = false; // 用于跟踪 blinkLED 的状态

int mqErrNum = 0;

PubSubClient mqClient(espClient);

void connect_mqtt(const char *mqtt_user, const char *mqtt_password)
{
    while (!mqClient.connected())
    {
        if(mqErrNum==150){
            preferences.begin("wifi-config", false); // 打开NVS
            preferences.clear();                     // 清除所有存储的键值对
            preferences.end();                       // 结束访问
            ESP.restart();
        }
        mqErrNum+=1;
        String clientId = "ESP32Client-";
        clientId.concat(macAddress);
        Serial.print(" Try Connect mqtt：");
        Serial.println(clientId);
        if (mqClient.connect(clientId.c_str(), mqtt_user, mqtt_password))
        { // MQTT连接成功
            Serial.println("Mqtt connected");
            mqClient.publish("esp32/status", createJsonMessage("OnLine").c_str());
            mqClient.subscribe(macAddress.c_str());

            mqClient.subscribe("home/esp32/relay/set"); // 订阅用于控制继电器的主题

            showTxt(0, 30, "Mqtt Ok!");
            u8g2.sendBuffer();
        }else
        {
            Serial.print("Mqtt connect failed with state: ");
            Serial.println(mqClient.state());
            delay(2000); // 2秒后重试
        }
    }

}
// 初始化esp32内部传感器
void initCpuSensor()
{
    temp_sensor_config_t temp_sensor = {
        .dac_offset = TSENS_DAC_L2,
        .clk_div = 6,
    };
    temp_sensor_set_config(temp_sensor);
    temp_sensor_start();
}
// 获取cpu温度
float getCpTtemperature()
{
    float tsens_out;
    temp_sensor_read_celsius(&tsens_out);
    return tsens_out;
}

String createJsonMessage(const char *status)
{

    StaticJsonDocument<200> doc;
    doc["sn"] = macAddress;
    doc["status"] = status;
    doc["rssi"] = WiFi.RSSI();
    doc["temperature"] = getCpTtemperature();
    doc["temperatureUnit"] = "°C";

    if (strcmp(status, "OnLine") == 0)
    {
        doc["ip"] = wifiIp;
        doc["name"] = deviceName;
        doc["os"] = os;
        doc["osNumber"] = osNumber;
    }

    String jsonString;
    serializeJson(doc, jsonString);
    return jsonString;
}

// LED闪烁
void blinkLED(int times, int interval)
{
    if (isBlinking)
        return;        // 如果 blinkLED 正在执行，则跳过新调用
    isBlinking = true; // 设置状态为正在执行

    for (int i = 0; i < times; i++)
    {
        digitalWrite(ledPin, LOW);
        delay(interval);
        digitalWrite(ledPin, HIGH);
        delay(interval);
    }

    isBlinking = false; // 恢复状态为未执行
}

void handlerOption(const String &jsonString)
{

    StaticJsonDocument<4096> doc;
    DeserializationError error = deserializeJson(doc, jsonString);
    if (!error)
    {
        const char *option = doc["option"];
        Serial.print("Option: ");
        Serial.println(option);
        showCommandLogo();

        if (strcmp(option, "power") == 0)
        { // 电源控制代码
            blinkLED(3, 200);

            sendPowerOnBack();

            powerControl();
        }
        else if (strcmp(option, "on") == 0)
        { // 开启风扇代码
            blinkLED(2, 400);

            openSwitch();
        }
        else if (strcmp(option, "off") == 0)
        { // 关闭风扇代码
            blinkLED(2, 400);

            closeSwitch();
        }
        else if (strcmp(option, "close") == 0)
        {                         // 关闭oled
            u8g2.setPowerSave(1); // 关闭显示
        }
        else if (strcmp(option, "reboot") == 0)
        { // 重启设备
            ESP.restart();
        }
        else if (strcmp(option, "reset") == 0)
        {                                            // 重置所有配置
            preferences.begin("wifi-config", false); // 打开NVS
            preferences.clear();                     // 清除所有存储的键值对
            preferences.end();                       // 结束访问
            ESP.restart();
        }
        else if (strcmp(option, "show") == 0)
        { // 显示图标
            showMqStatus = true;
            u8g2.clearBuffer();

            JsonArray items = doc["items"];
            // 遍历数组中的每个对象
            for (JsonObject item : items)
            {
                const char *type = item["type"];
                if (strcmp(type, "img") == 0)
                { // 渲染图片类
                    u8g2_uint_t xInt = item["x"];
                    u8g2_uint_t yInt = item["y"];

                    u8g2_uint_t wInt = item["w"];
                    u8g2_uint_t hInt = item["h"];

                    JsonArray logoData = item["logo"];
                    uint8_t array[logoData.size()];

                    for (size_t i = 0; i < logoData.size(); i++)
                    {
                        array[i] = logoData[i];
                    }
                    u8g2.drawXBM(xInt + 30, yInt + 14, wInt, hInt, array); // 30 14
                }
                if (strcmp(type, "e-txt") == 0)
                {
                    u8g2.setFont(u8g2_font_5x7_tr);
                    u8g2_uint_t xInt = item["x"];
                    u8g2_uint_t yInt = item["y"];
                    String valTxt = item["val"];

                    u8g2.setCursor(xInt + 30, yInt + 14);
                    u8g2.print(valTxt.c_str());
                }
                if (strcmp(type, "c-txt") == 0)
                {
                    u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
                    u8g2_uint_t xInt = item["x"];
                    u8g2_uint_t yInt = item["y"];
                    String valTxt = item["val"];

                    u8g2.setCursor(xInt + 30, yInt + 14);
                    u8g2.print(valTxt.c_str());
                }
            }

            u8g2.sendBuffer();
            delay(1500);
            showMqStatus = false;
        }
        else if (strcmp(option, "ota") == 0)
        { // ota升级
            String binUrl = doc["firmwar"];
            performOTAUpdate(binUrl);
        }
    }
    else
    {
        Serial.print("deserializeJson() failed: ");
        Serial.println(error.c_str());
    }
}

void callback(char *topic, byte *payload, unsigned int length)
{
    Serial.print("length:");
    Serial.print(length);
    String jsonString;
    for (unsigned int i = 0; i < length; i++)
    {
        jsonString += (char)payload[i];
    }
    Serial.println("Param：" + jsonString);

    // 处理home assistant
    if (String(topic) == "home/esp32/relay/set")
    {
        if (jsonString == "ON")
        {
            digitalWrite(switchPin3, switch3HighLevel ? HIGH : LOW);
            mqClient.publish("home/esp32/relay/state", "ON");
        }
        else if (jsonString == "OFF")
        {
            digitalWrite(switchPin3, switch3HighLevel ? LOW : HIGH);
            mqClient.publish("home/esp32/relay/state", "OFF");
        }
    }
    else
    {
        handlerOption(jsonString);
    }
}

void setupMqtt(const char *mqtt_server, const int mqtt_port, const char *mqtt_user, const char *mqtt_password)
{
    mqClient.setServer(mqtt_server, mqtt_port);
    mqClient.setCallback(callback);
}

void sendHeartBeat()
{ // 发送心跳包
    static unsigned long lastHeartbeat = 0;
    if (millis() - lastHeartbeat > 10000)
    {
        mqClient.publish("esp32/status", createJsonMessage("HeartBeat").c_str());
        lastHeartbeat = millis();
    }
}

void sendPowerOnBack()
{ // 发送开机执行反馈
    mqClient.publish("esp32/power", createPowerOnBackMessage().c_str());
}

//创建开机反馈消息
String createPowerOnBackMessage()
{

    StaticJsonDocument<200> doc;
    doc["status"] = "success";
    doc["ip"] = wifiIp;

    String jsonString;
    serializeJson(doc, jsonString);
    return jsonString;
}